package cn.yunyichina.provider.message.service.impl;

import cn.yunyichina.provider.framework.common.ResponseEnum;
import cn.yunyichina.provider.framework.dubbo.service.AlipayService;
import cn.yunyichina.provider.framework.dubbo.service.PayService;
import cn.yunyichina.provider.framework.exception.CallException;
import cn.yunyichina.provider.iface.entity.ErrorCodeDefine;
import cn.yunyichina.provider.iface.entity.alipay.AlipayRequest;
import cn.yunyichina.provider.iface.entity.alipay.AlipayResponse;
import cn.yunyichina.provider.iface.entity.common.ResCommon;
import cn.yunyichina.provider.iface.entity.common.ResponseObject;
import cn.yunyichina.provider.iface.entity.message.RegCardNoticeRequestVO;
import cn.yunyichina.provider.iface.entity.pay.PaymentSettingResponse;
import cn.yunyichina.utils.commons.DateUtils;
import cn.yunyichina.utils.convert.JsonUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

/**
 * 支付宝Card消息推送服务
 * Created by Lullaby on 2017/7/25
 */
@Service
public class CardMessageServiceImpl {

    private static Logger logger = LoggerFactory.getLogger(CardMessageServiceImpl.class);

    public ResponseObject sendCardMessage(String json) {
        logger.info("CardMessageImpl.sendCardMessage.json -> {}", json);

        ResponseObject response = new ResponseObject();

        JSONObject params = JsonUtils.parseObject(json);
        try {
            validParam(params, "noticeMode, template_id, user_id, app_code, data_type, operate, third_no, patient_name, hos_info, dept_info, doctor_info, treat_date, biz_type, order_link");
            validParam(JsonUtils.parseObject(params.get("hos_info")), "code, name, phone");
            validParam(JsonUtils.parseObject(params.get("dept_info")), "code, name, location");
            validParam(JsonUtils.parseObject(params.get("doctor_info")), "code, name, sex");

            if ((!StringUtils.isEmpty(params.getString("notify_time"))) &&
                    DateUtils.StringToDate(params.getString("notify_time")).before(Calendar.getInstance().getTime())) {
                throw new CallException(ErrorCodeDefine.MESSAGE_PARAM, "通知时间必须大于当前日期");
            }

            if ((StringUtils.isEmpty(params.getString("treat_date"))) &&
                    DateUtils.StringToDate(params.getString("treat_date")).before(Calendar.getInstance().getTime())) {
                throw new CallException(ErrorCodeDefine.MESSAGE_PARAM, "就诊时间必须大于当前日期");
            }

            RegCardNoticeRequestVO requestVO = JSON.parseObject(json, RegCardNoticeRequestVO.class);
            logger.info("CardMessageImpl.sendCardMessage.requestVO -> {}", JSON.toJSONString(requestVO));

            AlipayRequest sendRequest = buildSendRegCardMessageRequest(requestVO);
            logger.info("CardMessageImpl.sendCardMessage.sendRequest -> {}", JSON.toJSONString(sendRequest));

            ResCommon<AlipayResponse> sendResponse = AlipayService.getAlipayClient().sendCardMessage(sendRequest);
            logger.info("CardMessageImpl.sendCardMessage.sendResponse -> {}", JSON.toJSONString(sendResponse));

            if (sendResponse.isSuccess()) {
                response.setResultObject(sendResponse.getResult());
            } else {
                response.setResultCodeAndMessageAndResult(
                        sendResponse.getResultCode(),
                        sendResponse.getResultMessage(),
                        sendResponse.getResult()
                );
            }
        } catch (CallException e) {
            logger.error("CardMessageImpl.sendCardMessage.CallException", e);
            response.buildResultCodeAndMessage(
                    ResponseEnum.Common.INVALID.getCode(),
                    ResponseEnum.Common.INVALID.getMessage()
            );
        }

        return response;
    }

    private AlipayRequest buildSendRegCardMessageRequest(RegCardNoticeRequestVO requestVO) {
        String appId = requestVO.getAppId();
        ResCommon<PaymentSettingResponse> paymentSettingResponse = PayService.getPayClient().queryPaymentSettingByAppId(appId);

        if (!paymentSettingResponse.isSuccess()) {
            throw new CallException("-1", "Payment setting not found");
        }

        PaymentSettingResponse paymentSetting = paymentSettingResponse.getResult();

        AlipayRequest alipayRequest = new AlipayRequest();
        alipayRequest.setPublicKey(paymentSetting.getPublicKey());
        alipayRequest.setPrivateKey(paymentSetting.getPrivateKey());

        alipayRequest.setAppId(appId);
        alipayRequest.setMethod("alipay.eco.medicalcare.common.data.sync");
        alipayRequest.setFormat("JSON");
        alipayRequest.setCharset("utf-8");
        alipayRequest.setSignType("RSA");
        alipayRequest.setTimestamp(DateUtils.getDatetime());
        alipayRequest.setVersion("1.0");

        Map<String, Object> content = new HashMap<>();
        content.put("template_id", requestVO.getTemplateId());
        content.put("user_id", requestVO.getUserId());
        content.put("app_code", requestVO.getAppCode());
        content.put("data_type", requestVO.getDataType());

        Map<String, Object> dataBody = new HashMap<>();
        dataBody.put("operate", requestVO.getOperate());
        dataBody.put("third_no", requestVO.getThirdNo());
        dataBody.put("user_id", requestVO.getUserId());
        dataBody.put("patient_name", requestVO.getPatientName());
        dataBody.put("patient_card_type", requestVO.getPatientCardType());
        dataBody.put("patient_card_no", requestVO.getPatientCardNo());
        dataBody.put("hos_info", requestVO.getHosInfo());
        dataBody.put("dept_info", requestVO.getDeptInfo());
        dataBody.put("doctor_info", requestVO.getDoctorInfo());
        dataBody.put("treat_date", requestVO.getTreatDate());
        dataBody.put("treat_date_ext", requestVO.getTreatDateExt());
        if (!StringUtils.isEmpty(requestVO.getLineNo())) {
            dataBody.put("line_no", requestVO.getLineNo());
        }
        dataBody.put("biz_type", requestVO.getBizType());
        if (!StringUtils.isEmpty(requestVO.getNotifyTime())) {
            dataBody.put("notify_time", requestVO.getNotifyTime());
        }
        dataBody.put("cancel_reason", requestVO.getCancelReason());
        dataBody.put("order_link", requestVO.getOrderLink());
        dataBody.put("reg_link", requestVO.getRegLink());
        dataBody.put("cancel_desc", requestVO.getCancelDesc());
        dataBody.put("extend_params", requestVO.getExtendParams());

        content.put("data_body", dataBody);

        alipayRequest.setBizContent(JsonUtils.toJsonString(content));

        return alipayRequest;
    }

    private void validParam(JSONObject params, String fieldNames) {
        if (!StringUtils.isEmpty(fieldNames)) {
            String[] arrFieldName = fieldNames.split(",");
            for (String fieldName : arrFieldName) {
                if (StringUtils.isEmpty(params.getString(fieldName.trim()))) {
                    throw new CallException(ErrorCodeDefine.MESSAGE_PARAM, "参数异常" + fieldName.trim());
                }
            }
        }
    }

}
